package utils;

import java.math.BigDecimal;

/**
 * 红包工具类
 * @author bug-fsh
 */
public class RedPackUtils {

    /**
     * 随机分配红包算法
     * @param redPackConfig 红包配置模型
     * @return
     * @throws Exception
     */
    public static BigDecimal [] randRedPack(RedPackConfig redPackConfig) throws Exception {
        BigDecimal totalMoney = redPackConfig.getTotalMoney();
        BigDecimal minMoney = redPackConfig.getMinMoney();
        BigDecimal maxMoney = redPackConfig.getMaxMoney();
        int redPackNum = redPackConfig.getRedPackNum();
        if (!checkRedPackConfig(redPackConfig)) {
            throw new Exception("红包配置参数有误");
        }
        BigDecimal [] redPacks = new BigDecimal[redPackNum];
        for (int i = 0; i < redPackNum; i++) {
            redPacks[i] = minMoney;
        }
        totalMoney = totalMoney.subtract(minMoney.multiply(BigDecimal.valueOf(redPackNum)));
        while (totalMoney.compareTo(BigDecimal.valueOf(0)) > 0) {
            for (int i = 0; i < redPackNum; i++) {
                BigDecimal everyMoney = redPacks[i];
                if (everyMoney.compareTo(maxMoney) == 0) {
                    continue;
                }
                double min = 0.01;
                double max = maxMoney.subtract(everyMoney).doubleValue();
                BigDecimal addMoney = BigDecimal.valueOf(RandUtils.randNum(min, max)).setScale(2, BigDecimal.ROUND_FLOOR);
                if (addMoney.compareTo(totalMoney) > 0) {
                    addMoney = totalMoney;
                }
                redPacks[i] = redPacks[i].add(addMoney);
                totalMoney = totalMoney.subtract(addMoney);
            }
        }
        return redPacks;
    }

    /**
     * 检验红包配置参数是否正确
     * @param redPackConfig 红包配置模型
     * @return
     */
    public static boolean checkRedPackConfig(RedPackConfig redPackConfig) {
        boolean result = true;
        BigDecimal totalMoney = redPackConfig.getTotalMoney();
        BigDecimal minMoney = redPackConfig.getMinMoney();
        BigDecimal maxMoney = redPackConfig.getMaxMoney();
        int redPackNum = redPackConfig.getRedPackNum();
        //防止总金额小于0
        if (totalMoney.compareTo(BigDecimal.valueOf(0)) <= 0) {
            result = false;
        }
        //防止最小金额小于0
        if (result && minMoney.compareTo(BigDecimal.valueOf(0)) <= 0) {
            result = false;
        }
        //防止最大金额小于0
        if (result && maxMoney.compareTo(BigDecimal.valueOf(0)) <= 0) {
            result = false;
        }
        //防止红包数量小于0
        if (result && redPackNum <= 0) {
            result = false;
        }
        //防止总金额不够分配
        if (result && minMoney.multiply(BigDecimal.valueOf(redPackNum)).compareTo(totalMoney) > 0) {
            result = false;
        }
        //防止总金额分配不完
        if (result && maxMoney.multiply(BigDecimal.valueOf(redPackNum)).compareTo(totalMoney) < 0) {
            result = false;
        }
        return result;
    }

}

/**
 * 红包模型类
 */
class RedPackConfig {
    //红包总金额
    private BigDecimal totalMoney;
    //红包最小金额
    private BigDecimal minMoney;
    //红包最大金额
    private BigDecimal maxMoney;

    //红包数量
    private int redPackNum;

    public RedPackConfig(BigDecimal totalMoney, BigDecimal minMoney, BigDecimal maxMoney, int redPackNum) {
        this.totalMoney = totalMoney;
        this.minMoney = minMoney;
        this.maxMoney = maxMoney;
        this.redPackNum = redPackNum;
    }

    public BigDecimal getTotalMoney() {
        return totalMoney;
    }

    public void setTotalMoney(BigDecimal totalMoney) {
        this.totalMoney = totalMoney;
    }

    public BigDecimal getMinMoney() {
        return minMoney;
    }

    public void setMinMoney(BigDecimal minMoney) {
        this.minMoney = minMoney;
    }

    public BigDecimal getMaxMoney() {
        return maxMoney;
    }

    public void setMaxMoney(BigDecimal maxMoney) {
        this.maxMoney = maxMoney;
    }

    public int getRedPackNum() {
        return redPackNum;
    }

    public void setRedPackNum(int redPackNum) {
        this.redPackNum = redPackNum;
    }
}
